#include "static.h"


template static_container::map_container();
template map_container<REAL,3>::map_container();
template map_container<REAL,6>::map_container();


template<class T, int WIDTH>
map_container<T,WIDTH>::map_container(){
	this->indexmap = NULL;
	this->coefficients = NULL;
	this->size = 0;
	this->lindex = 0;
	this->null_element = 0;
};

template void map_container< qgcomplex ,11>::store_coefficients(const qgcomplex *, const rank11 *, const int &);
template void map_container< REAL, 3>::store_coefficients(const REAL *, const rank3 *, const int &);
template void map_container< REAL, 6>::store_coefficients(const REAL *, const rank6 *, const int &);

template<class T, int WIDTH>
void map_container<T, WIDTH>::store_coefficients( const T * data, const rank<INDEX, WIDTH> * map, const int & size){
	this->size = size;
	if(size > 0){
		this->indexmap = new rank<INDEX, WIDTH>[ this->size ];
		this->coefficients = new T [ this->size ];
		for(unsigned int i = 0; i < this->size; i++){
			this->indexmap[i] = map[i];
			this->coefficients[i] = data[i];
		}
	}
};

template void map_container< REAL, 3 >::store_coefficients(const vector< rank3 > & , const vector<REAL> &);
template void map_container< REAL, 6 >::store_coefficients(const vector< rank6 > & , const vector<REAL> &);
template void map_container< qgcomplex, 11 >::store_coefficients(const vector< rank11 > & , const vector< qgcomplex > &);

template<class T, int WIDTH>
void map_container<T, WIDTH>::store_coefficients( const vector<  rank<INDEX, WIDTH> > & imap, const vector<T> & data ){
	this->size = imap.size();
	this->indexmap = new rank<INDEX, WIDTH>[this->size];
	this->coefficients = new T [ this->size ];
	for(size_t i = 0; i < this->size; i++){
		this->indexmap[i] = imap[i];
		this->coefficients[i] = data[i];
	}
};

/*****************************************************************
  The function below stores the lindex as a static value locally in the
  function, and does not modify the class. This function is meant
  to be used with diagnostics scripts, not by the model itself.
 */

template void static_container::storevaluediag( const rank11 &, const qgcomplex & );

template<class T, int WIDTH>
void map_container<T,WIDTH>::storevaluediag(const rank<INDEX, WIDTH>  & r11, const T & value){
	int fiter = lindex+1;
	int biter = lindex;
	while(true){
		if( this->indexmap[fiter] == r11){
			lindex = fiter; break;
		}
		if( this->indexmap[biter] == r11 ){
			lindex = biter; break;
		}
		biter--;
		fiter++;
		if(fiter >= static_cast<int>(this->size) && biter < 0){
			throw cgcmexception("Could not find requested index.", -1);
		}
		if(fiter >= static_cast<int>(this->size)) fiter = this->size - 1;
		if(biter < 0) biter = 0;
	}
	this->coefficients[lindex] = value;
};


template const REAL * map_container< REAL, 3 >::getcoefficients() const;
template const REAL * map_container< REAL, 6 >::getcoefficients() const;
template const qgcomplex * map_container<  qgcomplex , 11 >::getcoefficients() const;

template<class T, int WIDTH>
const T * map_container<T,WIDTH>::getcoefficients() const{
	return this->coefficients;
};


template const rank3 * map_container< REAL, 3>::get_index_map() const;
template const rank6 * map_container< REAL, 6>::get_index_map() const;
template const rank11 * map_container< qgcomplex ,11>::get_index_map() const;


template<class T, int WIDTH>
const rank<INDEX, WIDTH> * map_container<T,WIDTH>::get_index_map() const{
	return this->indexmap;
}

template const int map_container<REAL,3>::get_size() const;
template const int map_container<REAL,6>::get_size() const;
template const int map_container< qgcomplex ,11>::get_size() const;

template<class T, int WIDTH>
const int map_container<T,WIDTH>::get_size() const{
	return this->size;
}

template const REAL & map_container<REAL,3>::getvalue(const rank3 &) const;
template const REAL & map_container<REAL,6>::getvalue(const rank6 &) const;
template const qgcomplex & map_container< qgcomplex ,11>::getvalue(const rank11 &) const;

template<class T, int WIDTH>
const T & map_container<T,WIDTH>::getvalue(
		const rank<INDEX, WIDTH>  & rpos) const{
	dassert( this-> size > 0, "Called getvalue with empty container." );
	int fiter = this->lindex;
	int biter = this->lindex -1 >= 0 ? this->lindex - 1 : 0;
	while(true){
		assert( static_cast<size_t>(fiter) < this->size );
		assert( biter >= 0 );
		if( this->indexmap[fiter] == rpos){
			*const_cast<int*>(&(this->lindex)) = fiter; break;
		}
		if( this->indexmap[biter] == rpos ){
			*const_cast<int*>( &(this->lindex) ) = biter; break;
		}
		biter--;
		fiter++;
		if(fiter >= static_cast<int>(this->size) && biter < 0){
			return this->null_element;
		}
		if(fiter >= static_cast<int>(this->size)) fiter = this->size - 1;
		if(biter < 0) biter = 0;
	}
	return this->coefficients[this->lindex];
}

template map_container<REAL, 3>::~map_container();
template map_container<REAL, 6>::~map_container();
template map_container< qgcomplex , 11>::~map_container();

template<class T, int WIDTH>
map_container<T,WIDTH>::~map_container(){
	this->size = 0;
	delete [] this->indexmap;
	delete [] this->coefficients;
};

